package dao

import (
	log "common/log4go"
	"crypto/tls"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"time"
)

const (
	httpMaxRetry = 3
	httpTimeout = 4 * time.Second
	httpImageTimeout = 4 * time.Second
	httpDeadline = 8 * time.Second
)

var (
	httpClient = &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				c, err := net.DialTimeout(netw, addr, httpTimeout)
				if err != nil {
					log.Error("net.DialTimeout(\"%s\", \"%s\", %d", netw, addr, httpTimeout)
					return nil, err
				}
				c.SetDeadline(time.Now().Add(httpDeadline))
				return c, nil
			},
			DisableKeepAlives: true,
			TLSClientConfig:   &tls.Config{InsecureSkipVerify: true},
		},
	}
)

// httpGet http request using get method
func HttpGet(url string) ([]byte, error) {
	var (
		resp *http.Response
		err error
	)
	for i := 1; i <= httpMaxRetry; i++ {
		resp, err = httpClient.Get(url)
		if err != nil {
			log.Error("httpClient.Get(\"%s\") try(%d) error(%v)", url, i, err)
			if resp != nil {
				resp.Body.Close()
			}
			continue
		}
		break
	}
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Error("ioutil.ReadAll(resp.Body) error(%v)", err)
		return nil, err
	}
	return body, nil
}

// httpPost http request using post method
func HttpPost(url string, data url.Values) ([]byte, error) {
	var (
		resp *http.Response
		err error
	)
	for i := 1; i <= httpMaxRetry; i++ {
		resp, err = httpClient.PostForm(url, data)
		if err != nil {
			log.Error("httpClient.Post(%s, %s) try(%d) resp(%v) error(%v)", url, data, i, resp, err)
			if resp != nil {
				resp.Body.Close()
			}
			continue
		}
		break
	}
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Error("ioutil.ReadAll(resp.Body) error(%v)", err)
		return nil, err
	}
	return body, nil
}

// httpGet http request using get method
func HttpDo(req *http.Request) ([]byte, error) {
	var (
		resp *http.Response
		err error
	)
	for i := 1; i <= httpMaxRetry; i++ {
		resp, err = httpClient.Do(req)
		if err != nil {
			log.Error("httpClient.Do(\"%s\") try(%d) error(%v)", req.RequestURI, i, err)
			continue
		}
		break
	}
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Error("ioutil.ReadAll(resp.Body) error(%v)", err)
		return nil, err
	}
	return body, nil
}

func HttpDoResp(req *http.Request) (*http.Response, error) {
	var (
		resp *http.Response
		err error
	)
	for i := 1; i <= httpMaxRetry; i++ {
		resp, err = httpClient.Do(req)
		if err != nil {
			log.Error("httpClient.Do(\"%s\") try(%d) error(%v)", req.RequestURI, i, err)
			continue
		}
		break
	}
	if err != nil {
		return nil, err
	}
	return resp, nil
}
